package com.yizisu.playerlibrary.view.video_view.view

import android.content.Context
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.core.view.GestureDetectorCompat
import com.yizisu.playerlibrary.view.video_view.helper.IPlayerConfig
import com.yizisu.playerlibrary.view.video_view.helper.IPlayerHelper
import com.yizisu.playerlibrary.view.video_view.helper.dip
import com.yizisu.playerlibrary.view.video_view.helper.getCountTimeByLong
import kotlin.math.abs
import kotlin.math.min

/**
 * 手势检测相关view
 * 1.滑动调节亮度
 * 2.滑动调节音量
 * 3.滑动调节进度
 * 4.长安倍速调节
 * 4.双击播放或者暂停
 */
open class PlayerGestureLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(
    context,
    attrs,
    defStyleAttr
), IPlayerHelper {

    private val tipView by lazy {
        PlayerTipsView(context).also {
            addView(it, LayoutParams(
                dip(120),
                LayoutParams.WRAP_CONTENT
            ).also {
                it.gravity = Gravity.CENTER
            })
        }
    }

    private var playerConfig: IPlayerConfig? = null

    /**
     * 展示或者隐藏操作栏
     */
    private val showOrHide
        get() = playerConfig?.playerControllerBarHelperData?.value


    private val speedHintView by lazy {
        PlayerTipsView(context).also {
            addView(it, LayoutParams(
                dip(120),
                LayoutParams.WRAP_CONTENT
            ).also {
                it.gravity = Gravity.CENTER_HORIZONTAL
                it.topMargin = dip(48)
            })
        }
    }

    override fun onAttachPlayerConfig(playerConfig: IPlayerConfig) {
        super.onAttachPlayerConfig(playerConfig)
        this.playerConfig = playerConfig
    }

    override fun isNeedPlayerListener(): Boolean {
        return true
    }

    /**
     * 当时是否是水平滑动
     * 水平滑动调节进度
     * 竖直滑动调节亮度或者音量
     */
    private var currentSwipeHorizontal: Boolean? = null
    private var totalDistance = 0f

    /**
     * 调节前的播放进度
     */
    private var beforeAdjustDuration = 0L

    /**
     * 调节后的播放进度
     */
    private var afterAdjustDuration = 0L

    /**
     * 手指滑动的视频总长度
     *  null,表示根据当前视频播放时长，默认十五分钟
     */
    private val maxSwipeDuration: Long?
        get() {
            val dis = resources.displayMetrics
            return if (dis.widthPixels < dis.heightPixels) {
                playerConfig?.maxSwipeDurationData?.value?.first
            } else {
                playerConfig?.maxSwipeDurationData?.value?.second
            }
        }

    /**
     * 上一次的播放进度
     */
    private var lastPlayerSpeed: Float? = null

    /**
     * 长按的播放倍速
     */
    private val longPressedSpeed: Float?
        get() = playerConfig?.longPressedSpeedData?.value

    /**
     * 是指响应触摸事件
     */
    private val enableGesture
        get() = playerConfig?.screenNotLockData?.value ?: true
    private val notAllowedTouch = 0.1f
    private fun isNotAllowedTouch(event: MotionEvent?): Boolean {
        event ?: return true
        return event.x < notAllowedTouch * width
                || event.x > width * (1 - notAllowedTouch)
                || event.y < notAllowedTouch * height
                || event.y > height * (1 - notAllowedTouch)
    }

    private val listener = object : GestureDetector.SimpleOnGestureListener() {
        override fun onDown(e: MotionEvent?): Boolean {
            //记录上次播放进度
            beforeAdjustDuration = playerConfig?.player?.currentDuration ?: 0L
            afterAdjustDuration = beforeAdjustDuration
            //将滑动方向设为null
            currentSwipeHorizontal = null
            //滑动总距离设置为0
            totalDistance = 0f
            tipView.visibility = View.INVISIBLE
            //返回true ，才有后续动作
            return enableGesture
        }

        override fun onScroll(
            downEvent: MotionEvent?,
            moveEvent: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            downEvent ?: return false
            tipView.visibility = View.VISIBLE
            val swipeHorizontal = currentSwipeHorizontal
                ?: (abs(distanceX) > abs(distanceY)).also {
                    currentSwipeHorizontal = it
                }
            if (swipeHorizontal) {
                //水平滑动
                totalDistance += distanceX
                swipeHorizontal(totalDistance, distanceX)
            } else {
                //竖直滑动
                totalDistance += distanceY
                if (downEvent.x < width / 2f) {
                    //在左区域竖直滑动
                    swipeLeft(totalDistance, distanceY)
                } else {
                    //在右区域竖直滑动
                    swipeRight(totalDistance, distanceY)
                }
            }
            return true
        }

        override fun onLongPress(e: MotionEvent?) {
            super.onLongPress(e)
            playerConfig?.player?.let {
                lastPlayerSpeed = it.getVideoSpeed()
                longPressedSpeed?.let { speed ->
                    it.setVideoSpeed(speed)
                    speedHintView.setTips("${it.getVideoSpeed()}播放中", null, null)
                    speedHintView.visibility = View.VISIBLE
                }
            }
        }

        override fun onDoubleTap(e: MotionEvent?): Boolean {
            playerConfig?.player?.let {
                if (it.isPlaying()) {
                    it.pause()
                } else {
                    it.play()
                }
            }
            return true
        }

        override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
            showOrHide?.autoShowOrHide()
            return true
        }
    }


    private val gestureDetectorCompat by lazy {
        GestureDetectorCompat(context, listener)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                actionUp()
            }
            MotionEvent.ACTION_DOWN -> {
                if (isNotAllowedTouch(event)) {
                    //不在触摸区域，不响应任何事件，防止误触
                    return super.onTouchEvent(event)
                }
            }
        }
        return if (enableGesture) {
            gestureDetectorCompat.onTouchEvent(event)
        } else {
            super.onTouchEvent(event)
        }
    }

    /**
     * 手指抬起，处理后续动作
     */
    private fun actionUp() {
        tipView.visibility = INVISIBLE
        speedHintView.visibility = INVISIBLE
        lastPlayerSpeed?.let {
            playerConfig?.player?.setVideoSpeed(it)
            lastPlayerSpeed = null
        }
        if (currentSwipeHorizontal == true && beforeAdjustDuration != afterAdjustDuration) {
            playerConfig?.player?.seekTo(afterAdjustDuration)
        }
    }


    /**
     * 水平滑动
     */
    private fun swipeHorizontal(totalOffset: Float, currentOffset: Float) {
        playerConfig?.player?.let {
            val totalDuration = it.totalDuration
            val totalText = getCountTimeByLong(totalDuration)
            //滑动的最大时长，取两个的最小值
            val swipeTotalDuration = min(maxSwipeDuration ?: totalDuration, totalDuration)
            //滑动的百分比，因为方向相反，取相反数
            val swipe = -totalOffset / width
            //最新进度值
            afterAdjustDuration = (beforeAdjustDuration + swipe * swipeTotalDuration).toLong()
            if (afterAdjustDuration <= 0L) {
                afterAdjustDuration = 0L
            }
            val currentText = getCountTimeByLong(afterAdjustDuration.toLong())
            tipView.setTips(
                "进度调节",
                "$currentText/${totalText}",
                afterAdjustDuration.toFloat() / totalDuration
            )
        }
    }

    /**
     * 左方竖直滑动
     */
    private fun swipeLeft(totalOffset: Float, currentOffset: Float) {
        //滑动的百分比,因为亮度有属性保存，所以每次用滑动值
        //亮度变化值是0-1f
        val swipe = currentOffset / height
        //当前值的百分比
        val currentLight = setScreenBrightnessSlide(swipe)
        tipView.setTips(
            "亮度调节",
            "${(currentLight * 100).toInt()}%",
            currentLight
        )
    }

    /**
     * 右方竖直滑动
     */
    private fun swipeRight(totalOffset: Float, currentOffset: Float) {
        //滑动的百分比
        val swipe = currentOffset / height
        val currentVolume = setVolume(swipe)
        tipView.setTips(
            "音量调节",
            "${(currentVolume * 100).toInt()}%",
            currentVolume
        )
    }
}